/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package indexacion;

import auxiliares.Log;
import buscador.IBuscador;
import buscador.ReduccionRaiz;
import buscador.TokensString;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Marco
 */
public class Indexador implements IAnalizador {

    private Indice indiceCreado;
    private IndiceDoc indiceDocCreado;
    private long tiempoIndexacion;
    private long tamEnDisco;
    private long tamEnDiscoDoc;
    private int numEntradas;
    private int numEntradasDoc;
    private HashMap<String, Integer> frecuenciasTokens = null;
    StopWords stopWords;

    public Indexador(StopWords palabrasVacias) throws ExcepcionIndexacion {

        tiempoIndexacion = -1;
        long tiempoInicio;
        this.tamEnDisco = 0;
        this.tamEnDiscoDoc = 0;
        this.numEntradas = 0;
        this.numEntradasDoc = 0;
        this.indiceCreado = new Indice();
        this.indiceDocCreado = new IndiceDoc();
        this.frecuenciasTokens = new HashMap<>();
        this.stopWords = palabrasVacias;
        File fichero = new File(IBuscador.FICHERO_INDICE);
        File ficheroDoc = new File(IBuscador.FICHERO_INDICEDOC);


        try {
            if (fichero.exists() && ficheroDoc.exists()) {

                tiempoInicio = System.currentTimeMillis();
                ObjectInputStream ois = new ObjectInputStream(new FileInputStream(IBuscador.FICHERO_INDICE));
                this.indiceCreado = (Indice) ois.readObject();
                ObjectInputStream oisDoc = new ObjectInputStream(new FileInputStream(IBuscador.FICHERO_INDICEDOC));
                this.indiceDocCreado = (IndiceDoc) oisDoc.readObject();
                tiempoIndexacion = System.currentTimeMillis() - tiempoInicio;

            } else {


                frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_ABREVIATURAS_COMPUESTAS, 0);
                frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_CONCEPTO_MEDICO, 0);
                frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_INTERVALOS, 0);
                frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_NUMEROS_DECIMALES, 0);
                frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_NUMEROS_ENTEROS, 0);
                frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_ORDINALES, 0);
                frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_PALABRAS, 0);
                frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_PORCENTAJES_DECIMALES, 0);
                frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_PORCENTAJES_ENTEROS, 0);
                frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_PROPORCIONES, 0);
                tiempoInicio = System.currentTimeMillis();
                this.indexarColeccion();
                tiempoIndexacion = System.currentTimeMillis() - tiempoInicio;

                if (null != this.indiceCreado && null != this.indiceDocCreado) {
                    this.indiceCreado.almacenar();
                    fichero = new File(IBuscador.FICHERO_INDICE);
                    this.indiceDocCreado.almacenar();
                    ficheroDoc = new File(IBuscador.FICHERO_INDICEDOC);

                }
            }
            this.numEntradas = this.indiceCreado.getNumEntradas();
            this.tamEnDisco = fichero.length();
            this.numEntradasDoc = this.indiceDocCreado.getNumEntradas();
            this.tamEnDiscoDoc = ficheroDoc.length();

        } catch (FileNotFoundException ex) {
            throw new ExcepcionIndexacion("No existe alguno o ambos de los ficheros de indice");
        } catch (IOException ex) {
            throw new ExcepcionIndexacion("Problema de E/S en los ficheros de indice");
        } catch (ClassNotFoundException ex) {
            throw new ExcepcionIndexacion("Problema al tratar de leer los ficheros de indice");
        }

    }

    public HashMap<String, Integer> getFrecuenciasTokens() {
        return this.frecuenciasTokens;
    }

    public StopWords getStopWords() {
        return this.stopWords;
    }

    public int getNumEntradas() {
        return this.numEntradas;
    }

    public int getNumEntradasDoc() {
        return this.numEntradasDoc;
    }

    @Override
    public long getTamIndiceDisco() {
        return this.tamEnDisco;
    }

    public long getTamIndiceDocDisco() {
        return this.tamEnDiscoDoc;
    }

    @Override
    public long getTIndexacion() {
        return this.tiempoIndexacion;
    }

    @Override
    public Indice getIndice() {
        return this.indiceCreado;
    }

    public IndiceDoc getIndiceDoc() {
        return this.indiceDocCreado;
    }

    @Override
    public void indexarDocumento(File nombreDoc) throws ExcepcionIndexacion {
        String titulo = null;
        int numeroLinea;
        Pattern patronIndiceDoc;
        int numPalabrasDocTratadas = 0;
        int indiceDoc = 0;
        int numDocumentosColeccion = this.indiceCreado.numeroDocsColeccion;
        Matcher m;
        //    File documento = new File(nombreDoc);

        String linea;
        TokensString segmentacionCadenas = new TokensString();

        if (nombreDoc == null) {
            throw new ExcepcionIndexacion("No hay ficheros que indexar");
        } else if (nombreDoc.canRead() && (0 < nombreDoc.length())) {

            // Se indexa cada fichero encontrado
            patronIndiceDoc = Pattern.compile("^\\.I ([0-9]+)");
            try {

                BufferedReader lecturaStream = new BufferedReader(new FileReader(nombreDoc.getCanonicalPath()));
                numeroLinea = 0;

                while ((linea = lecturaStream.readLine()) != null) {

                    // Se ha leido una linea mas, a tener en cuenta para
                    // localizar las palabras posteriormente
                    numeroLinea++;

                    // Se busca el identificador de un documento
                    m = patronIndiceDoc.matcher(linea);
                    if (m.find()) {
                        indiceDoc = Integer.parseInt(m.group(1));

                        numDocumentosColeccion++;
                        continue;
                    } // Si se encuentra la linea de inicio del abstract se puede
                    // comenzar a tratar el texto del documento
                    else if (0 == linea.compareTo(".W")) {
                        titulo = null;

                        continue;
                    } else {
                        // Si el titulo no existe aún significa que la linea
                        // es la primera de un nuevo documento
                        if (titulo == null) {
                            titulo = linea;

                            numPalabrasDocTratadas = 0;
                            indiceDocCreado.nuevoDoc(indiceDoc, nombreDoc.getName(), numeroLinea, titulo);
                        }
                        
                        numPalabrasDocTratadas = numPalabrasDocTratadas + analizarLinea(frecuenciasTokens, segmentacionCadenas, stopWords, linea, indiceDoc, titulo, numPalabrasDocTratadas);

                    }
                }
            } catch (IOException ex) {
                throw new ExcepcionIndexacion("Error al procesar los documentos de la coleccion");
            }

            this.indiceCreado.setNumDocumentosCol(numDocumentosColeccion);
            this.indiceCreado.almacenar();
            this.indiceDocCreado.almacenar();

        }
    }

    @Override
    public final void indexarColeccion() throws ExcepcionIndexacion {


        String titulo = null;
        int numeroLinea;
        Pattern patronIndiceDoc;
        int numPalabrasDocTratadas = 0;
        int indiceDoc = 0;
        int numDocumentosColeccion = 0;
        Matcher m;
        File documento, direcDocumentos = new File(IAnalizador.dirDocumentos);
        String[] ficheros = direcDocumentos.list();
        BufferedReader lecturaStream;
        String linea;
        TokensString segmentacionCadenas = new TokensString();

        if (ficheros == null) {
            throw new ExcepcionIndexacion("No hay ficheros que indexar");
        } else {
            // Se indexa cada fichero encontrado
            patronIndiceDoc = Pattern.compile("^\\.I ([0-9]+)");

            // Se preparan nuevos índices vacios
            this.indiceCreado = new Indice();
            this.indiceDocCreado = new IndiceDoc();

            for (int x = 0; x < ficheros.length; x++) {
                try {
                    documento = new File(direcDocumentos.getAbsolutePath() + System.getProperty("file.separator") + ficheros[x]);

                    if (documento.isFile() && (0 < documento.length())) {
                        lecturaStream = new BufferedReader(new FileReader(direcDocumentos + System.getProperty("file.separator") + documento.getName()));
                        numeroLinea = 0;

                        while ((linea = lecturaStream.readLine()) != null) {
                            // Se ha leido una linea mas, a tener en cuenta para
                            // localizar las palabras posteriormente
                            numeroLinea++;

                            // Se busca el identificador de un documento
                            m = patronIndiceDoc.matcher(linea);
                            if (m.find()) {
                                indiceDoc = Integer.parseInt(m.group(1));
                                numDocumentosColeccion++;
                                continue;
                            } // Si se encuentra la linea de inicio del abstract se puede
                            // comenzar a tratar el texto del documento
                            else if (0 == linea.compareTo(".W")) {
                                titulo = null;

                                continue;
                            } else {
                                // Si el titulo no existe aún significa que la linea
                                // es la primera de un nuevo documento
                                if (titulo == null) {
                                    titulo = linea;

                                    numPalabrasDocTratadas = 0;
                                    indiceDocCreado.nuevoDoc(indiceDoc, documento.getName(), numeroLinea, titulo);
                                }
                                numPalabrasDocTratadas = numPalabrasDocTratadas + analizarLinea(frecuenciasTokens, segmentacionCadenas, stopWords, linea, indiceDoc, titulo, numPalabrasDocTratadas);
                            }

                        }

                    }
                } catch (IOException ex) {
                    throw new ExcepcionIndexacion("Error al procesar los documentos de la coleccion");
                }
            }
            this.indiceCreado.setNumDocumentosCol(numDocumentosColeccion);

        }
    }

    private int analizarLinea(HashMap<String, Integer> frecuenciasTokens, TokensString segmentacion, StopWords stopWords, String linea, int indiceDoc, String tituloDoc, int numPalabrasAnalizadas) {

        ReduccionRaiz RedRaiz = new ReduccionRaiz();

        String expresionSignosPuntIzq = "[,;\\:\\(¿¡'\\[\\{\\.]*";
        String expresionSignosPuntDer = "[,;\\:\\)?!'\\]\\}\\.]*";

        String patronTokenPalabras = "(" + expresionSignosPuntIzq + "\\p{Alpha}+" + expresionSignosPuntDer + ")+";

        String patronTokenAbreviaturasCompuesto = "(\\p{Alpha}\\.){2,}+";

        String patronTokenPorcentajesEnteros = "(" + expresionSignosPuntIzq + "\\p{Digit}+%" + expresionSignosPuntDer + ")+";
        String patronTokenPorcentajesDecimales = "(" + expresionSignosPuntIzq + "[0-9]+[.,]{1}[0-9]+%" + expresionSignosPuntDer + ")+";

        String patronTokenNumerosEnteros = "(" + expresionSignosPuntIzq + "\\p{Digit}+" + expresionSignosPuntDer + ")+";
        String patronTokenNumerosDecimales = "(" + expresionSignosPuntIzq + "[0-9]+[.,]{1}[0-9]+" + expresionSignosPuntDer + ")+";
        String patronTokenOrdinales = "(" + expresionSignosPuntIzq + "[(\\p{Digit}+st)(\\p{Digit}+ST)(\\p{Digit}+nd)(\\p{Digit}+ND)(\\p{Digit}+rd)(\\p{Digit}+RD)(\\p{Digit}+th)(\\p{Digit}+TH)]" + expresionSignosPuntDer + ")+";

        String patronTokenIntervalosA = "(" + expresionSignosPuntIzq + "[\\p{Alpha}\\p{Digit}]+\\-[\\p{Alpha}\\p{Digit}]+" + expresionSignosPuntDer + ")+";
        String patronTokenIntervalosB = "(" + expresionSignosPuntIzq + "[0-9]+[.,]{1}[0-9]+-[\\p{Alpha}\\p{Digit}]+" + expresionSignosPuntDer + ")+";
        String patronTokenIntervalosC = "(" + expresionSignosPuntIzq + "[\\p{Alpha}\\p{Digit}]+\\-[0-9]+[.,]{1}[0-9]+" + expresionSignosPuntDer + ")+";
        String patronTokenIntervalosD = "(" + expresionSignosPuntIzq + "[0-9]+[.,]{1}[0-9]+\\-[0-9]+[.,]{1}[0-9]+" + expresionSignosPuntDer + ")+";

        String patronTokenProporcionesA = "(" + expresionSignosPuntIzq + "[(\\p{Alpha}+|\\p{Digit}+|\\p{Alpha}+.)/(\\p{Alpha}+|\\p{Digit}+|\\p{Alpha}+.)]+" + expresionSignosPuntDer + ")+";
        String patronTokenProporcionesB = "(" + expresionSignosPuntIzq + "[\\p{Alpha}\\p{Digit}]+/[\\p{Alpha}\\p{Digit}]+(?:\\-[\\p{Alpha}\\p{Digit}]+)*" + expresionSignosPuntDer + ")+";
        String patronTokenConceptoMedico = "(" + expresionSignosPuntIzq + "/(\\p{Alpha}+[ ]*)+\\.{0,1}/" + expresionSignosPuntDer + ")+";

        Pattern patronAbreviaturasCompuesto = Pattern.compile("((?:\\p{Alpha}\\.){2,}+)");

        Pattern patronPalabras = Pattern.compile("(\\p{Alpha}+)"); // Para filtrar palabras compuestas solo por letras
        Pattern patronConceptoMedico = Pattern.compile("(\\p{Alpha}+)"); // Para filtrar palabras en los conceptos medicos
        Pattern patronPorcentajesEnteros = Pattern.compile("(\\p{Digit}+%)"); // Para filtrar porcentajes enteros
        Pattern patronPorcentajesDecimales = Pattern.compile("([0-9]+[.,]{1}[0-9]+%)"); // Para filtrar porcentajes enteros
        Pattern patronNumerosEnteros = Pattern.compile("([\\-\\+]{0,1}[\\p{Digit}+(?:\\p{Digit}+\\.\\p{Digit}+)]+)"); // Para filtrar numeros enteros
        Pattern patronNumerosDecimales = Pattern.compile("([\\-\\+]{0,1}[0-9]+[.,]{1}[0-9]+)"); // Para filtrar numeros decimales
        Pattern patronOrdinales = Pattern.compile("(\\p{Digit}+st|\\p{Digit}+ST|\\p{Digit}+nd|\\p{Digit}+ND|\\p{Digit}+rd|\\p{Digit}+RD|\\p{Digit}+th|\\p{Digit}+TH)"); // Para filtrar ordinales
        Pattern patronIntervalosA = Pattern.compile("([\\p{Alpha}\\p{Digit}]+\\-[\\p{Alpha}\\p{Digit}]+(\\-[\\p{Alpha}\\p{Digit}]+)*)");
        Pattern patronIntervalosB = Pattern.compile("(\\p{Digit}+[.,]{1}\\p{Digit}+\\-[\\p{Alpha}\\p{Digit}]+)");
        Pattern patronIntervalosC = Pattern.compile("([\\p{Alpha}\\p{Digit}]+\\-[0-9]+[.,]{1}[0-9]+)");
        Pattern patronIntervalosD = Pattern.compile("([0-9]+[.,]{1}[0-9]+\\-[0-9]+[.,]{1}[0-9]+)");
        Pattern patronProporcionesA = Pattern.compile("((\\p{Alpha}+|\\p{Digit}+|\\p{Alpha}+.)/(\\p{Alpha}+|\\p{Digit}+|\\p{Alpha}+.))");
        Pattern patronProporcionesB = Pattern.compile("([\\p{Alpha}\\p{Digit}]+/[\\p{Alpha}\\p{Digit}]+(?:\\-[\\p{Alpha}\\p{Digit}]+)*)");

        String token;
        Matcher m;
        int j = 0;
        int frecuencia;
        int numTokensLinea;

        ArrayList<String> campos = segmentacion.getTokens(linea);
        numTokensLinea = campos.size();

        while (j < numTokensLinea) {

            token = campos.get(j++);

            // Se comprueba si es una abreviatura compuesta
            if (token.matches(patronTokenAbreviaturasCompuesto)) {
                m = patronAbreviaturasCompuesto.matcher(token);
                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_ABREVIATURAS_COMPUESTAS)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_ABREVIATURAS_COMPUESTAS) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_ABREVIATURAS_COMPUESTAS, frecuencia);
                    }
                }
            } else // Se comprueba si es un grupo de letras
            if (token.matches(patronTokenPalabras)) {
                m = patronPalabras.matcher(token);

                while (m.find()) {

                    // Se incluye la palabra solamente si no es una stop word
                    if (!stopWords.buscaStopWord(m.group(1))) {
                        for (int c = 0; c < m.group(1).length(); c++) {
                            RedRaiz.add(m.group(1).charAt(c));
                        }
                        RedRaiz.stem();
                        token = RedRaiz.toString();

                        this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);

                        // Contabiliza un token más de este tipo tratado
                        if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_PALABRAS)) {
                            frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_PALABRAS) + 1;
                            frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_PALABRAS, frecuencia);
                        }
                    }

                }
            } else // Se comprueba si es un concepto médico, palabras encerradas entre /
            if (token.matches(patronTokenConceptoMedico)) {
                m = patronConceptoMedico.matcher(token);
                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_CONCEPTO_MEDICO)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_CONCEPTO_MEDICO) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_CONCEPTO_MEDICO, frecuencia);
                    }
                }
            } else // Se comprueba si es un decimal 
            if (token.matches(patronTokenNumerosDecimales)) {
                m = patronNumerosDecimales.matcher(token);

                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_NUMEROS_DECIMALES)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_NUMEROS_DECIMALES) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_NUMEROS_DECIMALES, frecuencia);
                    }
                }
            } else // Se comprueba si es un porcentaje decimal
            if (token.matches(patronTokenPorcentajesDecimales)) {

                m = patronPorcentajesDecimales.matcher(token);

                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_PORCENTAJES_DECIMALES)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_PORCENTAJES_DECIMALES) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_PORCENTAJES_DECIMALES, frecuencia);
                    }
                }
            } else // Se comprueba si es un numero entero
            if (token.matches(patronTokenNumerosEnteros)) {
                m = patronNumerosEnteros.matcher(token);

                while (m.find()) {

                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_NUMEROS_ENTEROS)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_NUMEROS_ENTEROS) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_NUMEROS_ENTEROS, frecuencia);
                    }
                }
            } else // Se comprueba si es un numero ordinal
            if (token.matches(patronTokenOrdinales)) {
                m = patronOrdinales.matcher(token);

                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_ORDINALES)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_ORDINALES) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_ORDINALES, frecuencia);
                    }
                }
            } else // Se comprueba si es un intervalo
            if (token.matches(patronTokenIntervalosA)) {
                m = patronIntervalosA.matcher(token);

                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_INTERVALOS)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_INTERVALOS) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_INTERVALOS, frecuencia);
                    }
                }
            } else // Se comprueba si es un intervalo
            if (token.matches(patronTokenIntervalosB)) {
                m = patronIntervalosB.matcher(token);

                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_INTERVALOS)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_INTERVALOS) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_INTERVALOS, frecuencia);
                    }
                }
            } else // Se comprueba si es un intervalo
            if (token.matches(patronTokenIntervalosC)) {
                m = patronIntervalosC.matcher(token);

                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_INTERVALOS)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_INTERVALOS) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_INTERVALOS, frecuencia);
                    }
                }
            } else // Se comprueba si es un intervalo
            if (token.matches(patronTokenIntervalosD)) {
                m = patronIntervalosD.matcher(token);

                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_INTERVALOS)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_INTERVALOS) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_INTERVALOS, frecuencia);
                    }
                }
            } else // Se comprueba si es una proporcion   
            if (token.matches(patronTokenProporcionesA)) {
                m = patronProporcionesA.matcher(token);

                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_PROPORCIONES)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_PROPORCIONES) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_PROPORCIONES, frecuencia);
                    }
                }
            } else // Se comprueba si es una proporcion   
            if (token.matches(patronTokenProporcionesB)) {
                m = patronProporcionesB.matcher(token);

                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_PROPORCIONES)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_PROPORCIONES) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_PROPORCIONES, frecuencia);
                    }
                }
            } else // Se comprueba si es un porcentaje entero
            if (token.matches(patronTokenPorcentajesEnteros)) {
                m = patronPorcentajesEnteros.matcher(token);

                while (m.find()) {
                    token = m.group(1);
                    this.indiceCreado.addEntrada(token, indiceDoc, tituloDoc, j + numPalabrasAnalizadas);
                    // Contabiliza un token más de este tipo tratado
                    if (null != frecuenciasTokens && frecuenciasTokens.containsKey(IAnalizador.TIPO_TOKEN_PORCENTAJES_ENTEROS)) {
                        frecuencia = frecuenciasTokens.remove(IAnalizador.TIPO_TOKEN_PORCENTAJES_ENTEROS) + 1;
                        frecuenciasTokens.put(IAnalizador.TIPO_TOKEN_PORCENTAJES_ENTEROS, frecuencia);
                    }
                }
            }
        }
        return numTokensLinea;
    }
}
